package com.jy.modules.cims.component.image;

import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @description 多线程文件下载
 * @author shengzhoutao
 * @date 2015-09-29
 */
public class FileDownloader {
	private final int THREAD_POOL_SIZE = 6;// 定义线程池大小
	private static Logger logger = LoggerFactory.getLogger(FileDownloader.class);
	private volatile static FileDownloader fileDownloader;

	public static FileDownloader getFileDownloader() {
		if (fileDownloader == null) {
			synchronized (FileDownloader.class) {
				if (fileDownloader == null) {
					fileDownloader = new FileDownloader();
				}
			}
		}
		return fileDownloader;
	}

	// 线程池
	private final ExecutorService executor = Executors.newFixedThreadPool(THREAD_POOL_SIZE);

	/**
	 * @description 下载
	 * @param url
	 *            URL地址
	 * @param path
	 *            文件
	 * @return
	 */
	public boolean download(final URL url, final Path path) {
		Future<Path> future = executor.submit(new Callable<Path>() { // submit提交任务
					public Path call() {
						InputStream inputStream = null;
						try {
							inputStream = url.openStream();
							Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
						} catch (IOException e) {
							logger.error(e.getMessage());
						} finally {
							if (null != inputStream) {
								try {
									inputStream.close();
								} catch (IOException e) {
									logger.error(e.getMessage());
								}
							}
						}
						return path;
					}
				});
		try {
			return future.get() != null ? true : false;
		} catch (Exception e) {
			logger.error(e.getMessage());
			return false;
		}
	}

	/**
	 * @description
	 */
	public void close() {// 当不再使用FileDownloader类的对象时，应该使用close方法关闭其中包含的ExecutorService接口的实现对象，否则虚拟机不会退出，占用内存不释放
		executor.shutdown();// 发出关闭请求，此时不会再接受新任务
		try {
			if (!executor.awaitTermination(3, TimeUnit.MINUTES)) {// awaitTermination
																	// 来等待一段时间，使正在执行的任务或等待的任务有机会完成
				executor.shutdownNow();// 如果等待时间过后还有任务没完成，则强制结束
				executor.awaitTermination(1, TimeUnit.MINUTES);// 再等待一段时间，使被强制结束的任务完成必要的清理工作
			}
		} catch (InterruptedException e) {
			executor.shutdownNow();
			Thread.currentThread().interrupt();
		}
	}
}